//: Playground - noun: a place where people can play

import UIKit

//: ### Function

//: ### The most simple function

//
func printName(){
    print("My name is zmj")
}

printName()

//: ### Function param

func multipleOfTen(multiplier: Int) {
    print("\(multiplier) * 10 = \(multiplier * 10)")
}

multipleOfTen(10)

func multipleOf(multiplier: Int, andValue: Int) {
    print("\(multiplier) * \(andValue) = \(multiplier * andValue)")
}

multipleOf(5, andValue: 10)

//: param name
// innername
func createTable(row: Int, colNumber column: Int) {
    print("Table: \(row) * \(column)")
}

createTable(10, colNumber: 10)

//: Default value

//: Variadic param
func arraySum(number: Double...) {
    var sum: Double = 1.0
    for i in number {
        sum *= i
    }
    print("sum: \(sum)")
}

arraySum(10, 1, 4, 5.3, 23.4, 5.3)
arraySum(1, 4, 5, 3, 6, 9)

let ten = 10
var addClosure: (Int, Int) -> Int = { (a:Int, b: Int) -> Int in
    return a + b }

addClosure(5, 10)

addClosure = {a, b in return a + b }
addClosure(10, 3)

//Single expression
addClosure = {a, b in a + b}
addClosure(4, 5)
//$0, 1, 2, 3
addClosure = {$0 + $1}

addClosure(1, 6)

func execute(a: Int, _ b: Int, operation: (Int, Int) -> Int) -> Int { return operation(a,b) }

func addFunc(a: Int, _ b: Int) -> Int{ return a * b }

execute(3, 20, operation: addClosure)
execute(3, 20, operation: addFunc)

execute(3, 20, operation: { (a: Int, b: Int) -> Int in return a / b })

execute(4, 20, operation: { a, b in a + b})

execute(1, 10) {$0 % $1}

// void
let voidClosure: () -> Void = { print("Swift is fun")}

//: Capturing value

// Scope

// Global

// if {} while {} func { new scope}

var count = 0
let increment = { count += 1 }
increment()
increment()
increment()
increment()

count

func counting() -> () -> Int {
    var count = 0
    let incrementCount: () -> Int = {
        count += 1
        return count
    }
    return incrementCount
}

let c1 = counting()
c1()
c1()

let c2 = counting()
c2()
c2()
c2()


//: ### Build your own type
//: Int String
/**
 *  @author zmj, 16-01-06 21:01:32
 *
 *  location (Double, Double)
 name  (String, String)
 */

//: named types
//: struct class enum protocol
//: #### struct - value type




//: Class
//: final 不能被继承，修改

class TV{
    var keyName = "12"
    var keyCount = "Power!"
    var name:String = "Xiaomi"
    func openTV() -> String{
        return "Success"
    }
    init(name: String) {
        self.name = name
    }
    deinit{
        name = ""
    }
    func getMyTVKeys() -> Int {
        return 12
    }
}

var miTV = TV(name: "abcde")
print(miTV.keyName)

var myTV = miTV
myTV.keyName = "Sundy"

print(miTV.keyName, myTV.keyName)

var myTV1 = TV(name: "Sundy's TV")
print(myTV1.name)

class MITV:TV{
    //重写构造函数
    override init(name: String) {
        super.init(name: name)
        super.name = "hello: \(name)"
    }
    //重写属性
    override var name:String {
        get{
            return self.name
        }
        set{
            if (name == "Sundy"){
                super.name = "Hello Sundy'Family"
            }else{
                super.name = "Hello"
            }
        }
    }
    //重写函数
    override func getMyTVKeys() -> Int {
        return 24
    }
    //新的函数
    func getMyTVKeys(name: String) -> String {
        return "diff \(name)"
    }
}

var myMinTV = MITV(name: "zmj")

//继承了构造函数
print("\(myMinTV.name)")
//继承了函数
print("\(myMinTV.getMyTVKeys())")

print("\(myMinTV.getMyTVKeys("明星"))")

/**
 //类和结构体的差别与相同点
 //相同点：
 1.都是有内部变量和函数
 2.都可以有内部下表方式去取属性
 3.都可以有初始化函数
 4.都可以用协议
 
 不同点:
 1.类有继承，
 2.类可以多重引用
 3.类有析构
 
 **/


/**
 //: protocol
 protocol Action{
 var myName:String{
 get{
 }
 
 }
 var myAge:(Int){
 get
 }
 func getMyName() -> String
 init(){
 
 }
 }
 
 class InvokeAction:Action{
 var m_name:String?
 var myName:String{
 get{
 return "Sundy"
 }set{
 m_name = newValue
 }
 }
 var myAction:Int{
 get{
 
 }
 }
 }
 
 */


//练习题
func addString (str1: String, str2: String) -> Int? {
    let int1: Int? = Int(str1)
    let int2: Int? = Int(str2)
    return int1! + int2!
}

print("\(addString("10", str2: "20"))")




//有效性检查,可空绑定和强制拆箱
let wrappedFalseBool: Bool? = false
if wrappedFalseBool == true {
    print("wrappedFalseBool false")
}

if wrappedFalseBool != nil {
    print("True because the optional has a wrapped value")
}


//函数
class Person {
    var firstName:  String!
    var middleName: String?
    var lastName:   String?
    var job:        String?
    var age:        Int?
    
    init(firstName: String) {
        self.firstName = firstName
    }
    
    convenience init(firstName name: String, job: String) {
        self.init(firstName: name)
        self.job = job
    }
    //签名不能跟其他便利初始化方法一样
    convenience init(beginName name: String, defaultJob: String = "iOS") {
        self.init(firstName: name)
        self.job = defaultJob
    }
}

let person01 = Person(firstName: "zmj", job: "iOS")
let peroson02 = Person(firstName: "wjl")
let person03 = Person(beginName: "baby", defaultJob: "Sleep")

